﻿using System;
using System.Collections.Generic;
using Assist;
using Autodesk.Revit.DB;
using YJKArchUtils.Utils;
using YJKRevitDimensionText.OneKeyPlanDim.Utility;

namespace YJKRevitDimensionText.OneKeyPlanDim.DimData
{
	public class DbSteps : DbDimBase
	{
		public DbSteps(FamilyInstance step)
		{
			this.m_FsStep = step;
		}

		public XYZ CenterPoint
		{
			get
			{
				this.AnalysisInfo();
				if (this.m_lstPlanarFaceZ.Count > 0)
				{
					return GeometryHelper.GeometricCenterOfPlanarFace(this.m_lstPlanarFaceZ[0]);
				}
				return XYZ.Zero;
			}
		}

		public XYZ OriginPoint
		{
			get
			{
				this.AnalysisInfo();
				if (this.m_BottomAndBehindLine != null)
				{
					return this.m_Centerline.Origin;
				}
				return XYZ.Zero;
			}
		}

		public override bool CreateSizeDim(Autodesk.Revit.DB.Document doc)
		{
			if (!base.CreateSizeDim(doc))
			{
				return false;
			}
			if (!this.AnalysisInfo())
			{
				return false;
			}
			this.CreateSizeRef();
			Dimension dimension = new SizeDimData(this.m_doc, this.m_Centerline, this.m_arRef).CreateDim(true);
			if (dimension == null)
			{
				return false;
			}
			this.ChangeText(dimension);
			this.SetDimPosition(dimension);
			return true;
		}

		private void ChangeText(Dimension newDim)
		{
			if (this.m_lstPlanarFaceZ.Count > 6)
			{
				double num = double.MaxValue;
				DimensionSegment dimensionSegment = null;
				DimensionSegmentArray segments = newDim.Segments;
				for (int i = 0; i < segments.Size; i++)
				{
                    double num2 = this.m_DimensionSegmentCenterPt.DistanceTo(segments.get_Item(i).Origin);
					if (Geometry.LessThan(num2, num))
					{
						num = num2;
                        dimensionSegment = segments.get_Item(i);
					}
				}
				if (dimensionSegment != null)
				{
					using (Transaction transaction = new Transaction(this.m_doc, "ChangeVal"))
					{
						try
						{
							transaction.Start();
							dimensionSegment.ValueOverride = this.m_strDimensionSegmentTxt;
							transaction.Commit();
						}
						catch
						{
							transaction.RollBack();
						}
					}
				}
			}
		}

		private void SetDimPosition(Dimension newDim)
		{
			List<CurveLoop> componentAndSizeAndSlopeOcclusionArea = OcclusionArea.GetInstance().GetComponentAndSizeAndSlopeOcclusionArea();
			List<CurveLoop> sizeDimCurveLoop = OcclusionArea.GetSizeDimCurveLoop(newDim);
			XYZ origin = this.m_Centerline.Origin;
			XYZ ptEnd = origin;
			List<CurveLoop> list = new List<CurveLoop>();
			double dOffsetDistance = Common.MMToFeet(600.0) * (double)(this.m_doc.ActiveView.Scale / 100);
			for (int i = 0; i < 9; i++)
			{
				ptEnd = CommonInterface.GetNumCorrespondingOffsetPoint(i, dOffsetDistance, origin, this.m_LevelDir);
				list = CommonInterface.MoveLstCurve(sizeDimCurveLoop, origin, ptEnd);
				bool flag = false;
				using (List<CurveLoop>.Enumerator enumerator = list.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						if (CommonInterface.IsExistOcclusion(enumerator.Current, componentAndSizeAndSlopeOcclusionArea))
						{
							flag = true;
							break;
						}
					}
				}
				if (!flag)
				{
					break;
				}
				if (8 == i)
				{
					ptEnd = origin;
					break;
				}
			}
			OcclusionArea.GetInstance().m_lstSizeDimCvLoop.AddRange(list);
			CommonInterface.MoveElement(newDim, origin, ptEnd, this.m_doc);
		}

		public override bool CreateLevelDim(Autodesk.Revit.DB.Document doc, out List<SingleLevelDimDataInfo> lstSingleLevelDimDataInfo)
		{
			if (!base.CreateLevelDim(doc, out lstSingleLevelDimDataInfo))
			{
				return false;
			}
			if (!this.AnalysisInfo())
			{
				return false;
			}
			if (this.m_lstPlanarFaceZ.Count < 2)
			{
				return false;
			}
			this.m_lstPlanarFaceZ[this.m_lstPlanarFaceZ.Count - 1].Origin.Z.ToString("f3");
			this.CreateTopLevelDim(ref lstSingleLevelDimDataInfo, this.m_lstPlanarFaceZ[this.m_lstPlanarFaceZ.Count - 1]);
			this.CreateBottomLevelDim(ref lstSingleLevelDimDataInfo, this.m_lstPlanarFaceZ[0]);
			return true;
		}

		public override bool CreateSlopeDim(Autodesk.Revit.DB.Document doc)
		{
			return base.CreateSlopeDim(doc);
		}

		public bool AnalysisInfo()
		{
			if (!base.IsNeedAnalysisInfo())
			{
				return true;
			}
			try
			{
				List<PlanarFace> allPlanarFace = GeometryHelper.GetAllPlanarFace(this.m_FsStep);
				this.m_lstPlanarFaceZ = GeometryHelper.GetBasePlanarFace(allPlanarFace);
				this.m_lstPlanarFaceZ.Sort(new PlanarFaceComparer());
				List<PlanarFace> lstAllPlanarFace = this.AllPlanarFaceNoLadderFace(allPlanarFace, this.m_lstPlanarFaceZ[this.m_lstPlanarFaceZ.Count - 1].Origin, this.m_lstPlanarFaceZ[0].Origin);
				this.CalLadderDirAndCenterAxis(lstAllPlanarFace);
				if (this.m_lstPlanarFaceZ.Count > 0)
				{
					List<CurveLoop> list = new List<CurveLoop>();
					foreach (CurveLoop curveLoop in this.m_lstPlanarFaceZ[0].GetEdgesAsCurveLoops())
					{
						CurveLoop xyplaneCurve = CommonInterface.GetXYPlaneCurve(curveLoop);
						list.Add(xyplaneCurve);
					}
					OcclusionArea.GetInstance().AddRampCurve(this.m_FsStep.Id, list);
				}
			}
			catch
			{
				return false;
			}
			return true;
		}

		private bool CreateTopLevelDim(ref List<SingleLevelDimDataInfo> lstSingleLevelDimDataInfo, PlanarFace topPlanarFace)
		{
			double levelVal = Common.FeetToMM(this.m_lstPlanarFaceZ[this.m_lstPlanarFaceZ.Count - 1].Origin.Z) / 1000.0;
			string dimVal = levelVal.ToString("f3");
			XYZ xyz = GeometryHelper.GeometricCenterOfPlanarFace(topPlanarFace);
			FamilyInstance familyInstance = new LevelDimData(this.m_doc)
			{
				PtDimLocation = xyz,
				DimVal = dimVal
			}.CreateLevelDim();
			if (familyInstance == null)
			{
				return false;
			}
			AnnotationSymbol annotationSymbol = familyInstance as AnnotationSymbol;
			if (annotationSymbol != null)
			{
				SingleLevelDimDataInfo singleLevelDimDataInfo = new SingleLevelDimDataInfo(annotationSymbol);
				singleLevelDimDataInfo.LevelVal = levelVal;
				singleLevelDimDataInfo.LadderLineLength = this.m_BottomAndBehindLine.Length;
				singleLevelDimDataInfo.DimDir = this.m_stepDir;
				singleLevelDimDataInfo.PtLocation = xyz;
				singleLevelDimDataInfo.bStepDownDim = false;
				singleLevelDimDataInfo.m_LstElementId.Add(this.m_FsStep.Id);
				lstSingleLevelDimDataInfo.Add(singleLevelDimDataInfo);
			}
			return true;
		}

		private bool CreateBottomLevelDim(ref List<SingleLevelDimDataInfo> lstSingleLevelDimDataInfo, PlanarFace bottomPlanarFace)
		{
			List<Curve> allEdgeList = GeometryHelper.GetAllEdgeList(bottomPlanarFace);
			List<XYZ> list = GeometryHelper.LineWithLstCvIntersect(this.m_Centerline, allEdgeList);
			if (list.Count != 2)
			{
				return false;
			}
			XYZ xyz = list[0];
			if (Geometry.LessThan(list[0].DistanceTo(this.OriginPoint), list[1].DistanceTo(this.OriginPoint)))
			{
				xyz = list[1];
			}
			XYZ dimDir = this.m_stepDir.CrossProduct(XYZ.BasisZ).Normalize();
			xyz -= this.m_stepDir * (Common.MMToFeet(1500.0) * (double)this.m_doc.ActiveView.Scale / 100.0);
			if (base.ComponentInSlopePlanarFace != null)
			{
				xyz = CommonInterface.PtInPlanarFaceInDir(xyz, base.ComponentInSlopePlanarFace, XYZ.BasisZ);
			}
			FamilyInstance familyInstance = new LevelDimData(this.m_doc)
			{
				PtDimLocation = xyz,
				DimVal = base.FloorLevelVal
			}.CreateLevelDim();
			if (familyInstance == null)
			{
				return false;
			}
			AnnotationSymbol annotationSymbol = familyInstance as AnnotationSymbol;
			if (annotationSymbol != null)
			{
				SingleLevelDimDataInfo singleLevelDimDataInfo = new SingleLevelDimDataInfo(annotationSymbol);
				if (base.ComponentInSlopePlanarFace != null)
				{
					singleLevelDimDataInfo.LevelVal = Common.FeetToMM(xyz.Z) / 1000.0;
				}
				else
				{
					singleLevelDimDataInfo.LevelVal = base.dFloorLevelVal;
				}
				singleLevelDimDataInfo.LadderLineLength = this.m_BottomAndBehindLine.Length;
				singleLevelDimDataInfo.DimDir = dimDir;
				singleLevelDimDataInfo.PtLocation = xyz;
				singleLevelDimDataInfo.bStepDownDim = true;
				singleLevelDimDataInfo.m_LstElementId.Add(this.m_FsStep.Id);
				lstSingleLevelDimDataInfo.Add(singleLevelDimDataInfo);
			}
			return true;
		}

		private List<PlanarFace> AllPlanarFaceNoLadderFace(List<PlanarFace> lstAllPlanarFace, XYZ topPt, XYZ bottomPt)
		{
			List<PlanarFace> list = new List<PlanarFace>();
			foreach (PlanarFace planarFace in lstAllPlanarFace)
			{
				if (!GeometryHelper.VectorParallelVector(XYZ.BasisZ, planarFace.FaceNormal) && planarFace.Project(topPt) != null && planarFace.Project(bottomPt) != null)
				{
					list.Add(planarFace);
				}
			}
			return list;
		}

		private void CalLadderDirAndCenterAxis(List<PlanarFace> lstAllPlanarFace)
		{
			if (lstAllPlanarFace.Count == 1)
			{
				this.AnalysisSingleEdgeOrBowStep(lstAllPlanarFace[0]);
				return;
			}
			if (lstAllPlanarFace.Count == 2)
			{
				this.AnalysisTwoSideRectStep(lstAllPlanarFace[0], lstAllPlanarFace[1]);
				return;
			}
			if (lstAllPlanarFace.Count == 3)
			{
				this.AnalysisThreeSideRectStep(lstAllPlanarFace[0], lstAllPlanarFace[1], lstAllPlanarFace[2]);
			}
		}

		private void AnalysisSingleEdgeOrBowStep(PlanarFace sideFace)
		{
			this.m_BottomAndBehindLine = this.GetBaseEdgeInPlanarFace(sideFace);
			if (this.m_BottomAndBehindLine == null)
			{
				return;
			}
			this.CalLadderDirAndCenterAxisByLine(this.m_BottomAndBehindLine);
		}

		private void AnalysisTwoSideRectStep(PlanarFace sideFace1, PlanarFace sideFace2)
		{
			Line baseEdgeInPlanarFace = this.GetBaseEdgeInPlanarFace(sideFace1);
			if (baseEdgeInPlanarFace == null)
			{
				return;
			}
			Line baseEdgeInPlanarFace2 = this.GetBaseEdgeInPlanarFace(sideFace2);
			if (baseEdgeInPlanarFace2 == null)
			{
				return;
			}
			this.m_BottomAndBehindLine = baseEdgeInPlanarFace;
			if (Geometry.LessThan(baseEdgeInPlanarFace.Length, baseEdgeInPlanarFace2.Length))
			{
				this.m_BottomAndBehindLine = baseEdgeInPlanarFace2;
			}
			this.CalLadderDirAndCenterAxisByLine(this.m_BottomAndBehindLine);
		}

		private void AnalysisThreeSideRectStep(PlanarFace sideFace1, PlanarFace sideFace2, PlanarFace sideFace3)
		{
			List<Curve> allEdgeList = GeometryHelper.GetAllEdgeList(sideFace1);
			if (allEdgeList.Count == 4)
			{
				this.m_BottomAndBehindLine = this.GetBaseEdgeInPlanarFace(allEdgeList);
				this.CalLadderDirAndCenterAxisByLine(this.m_BottomAndBehindLine);
				return;
			}
			allEdgeList = GeometryHelper.GetAllEdgeList(sideFace2);
			if (allEdgeList.Count == 4)
			{
				this.m_BottomAndBehindLine = this.GetBaseEdgeInPlanarFace(allEdgeList);
				this.CalLadderDirAndCenterAxisByLine(this.m_BottomAndBehindLine);
				return;
			}
			allEdgeList = GeometryHelper.GetAllEdgeList(sideFace3);
			if (allEdgeList.Count == 4)
			{
				this.m_BottomAndBehindLine = this.GetBaseEdgeInPlanarFace(allEdgeList);
				this.CalLadderDirAndCenterAxisByLine(this.m_BottomAndBehindLine);
				return;
			}
		}

		private void CalLadderDirAndCenterAxisByLine(Line line)
		{
			this.m_stepDir = line.Direction.CrossProduct(XYZ.BasisZ).Normalize();
			XYZ xyz = (line.GetEndPoint(0) + line.GetEndPoint(1)) / 2.0;
			this.m_Centerline = Line.CreateUnbound(new XYZ(xyz.X, xyz.Y, 0.0), this.m_stepDir);
			if (this.m_lstPlanarFaceZ[0].Project(xyz + this.m_stepDir * Common.MMToFeet(100.0)) != null)
			{
				this.m_stepDir = -this.m_stepDir;
			}
			this.m_LevelDir = this.m_stepDir.CrossProduct(XYZ.BasisZ);
		}

		private Line GetBaseEdgeInPlanarFace(PlanarFace sideFace)
		{
			List<Curve> allEdgeList = GeometryHelper.GetAllEdgeList(sideFace);
			Line result = null;
			double num = double.MaxValue;
			foreach (Curve curve in allEdgeList)
			{
				if (curve is Line && Geometry.IsEqual(curve.GetEndPoint(0).Z, curve.GetEndPoint(1).Z) && Geometry.LessThan(curve.GetEndPoint(0).Z, num))
				{
					num = curve.GetEndPoint(0).Z;
					result = (curve as Line);
				}
			}
			return result;
		}

		private Line GetBaseEdgeInPlanarFace(List<Curve> lstCv)
		{
			Line result = null;
			double num = double.MaxValue;
			foreach (Curve curve in lstCv)
			{
				if (curve is Line && Geometry.IsEqual(curve.GetEndPoint(0).Z, curve.GetEndPoint(1).Z) && Geometry.LessThan(curve.GetEndPoint(0).Z, num))
				{
					num = curve.GetEndPoint(0).Z;
					result = (curve as Line);
				}
			}
			return result;
		}

		private void CreateSizeRef()
		{
			List<Curve> list = new List<Curve>();
			List<XYZ> list2 = new List<XYZ>();
			if (this.m_lstPlanarFaceZ.Count > 6)
			{
				int num = this.m_lstPlanarFaceZ.Count - 2;
				XYZ xyz = XYZ.Zero;
				list.AddRange(GeometryHelper.GetAllEdgeList(this.m_lstPlanarFaceZ[0]));
				List<XYZ> list3 = GeometryHelper.LineWithLstCvIntersect(this.m_Centerline, list);
				if (list3.Count == 2)
				{
					if (Geometry.LessThan(this.m_BottomAndBehindLine.Distance(list3[0]), this.m_BottomAndBehindLine.Distance(list3[1]), 0.001))
					{
						xyz = list3[1];
					}
					else
					{
						xyz = list3[0];
					}
				}
				list2.AddRange(list3);
				list.Clear();
				list.AddRange(GeometryHelper.GetAllEdgeList(this.m_lstPlanarFaceZ[this.m_lstPlanarFaceZ.Count - 1]));
				list3 = GeometryHelper.LineWithLstCvIntersect(this.m_Centerline, list);
				if (list3.Count == 2)
				{
					double num2;
					if (Geometry.LessThan(xyz.DistanceTo(list3[0]), xyz.DistanceTo(list3[1]), 0.001))
					{
						num2 = xyz.DistanceTo(list3[0]);
						this.m_DimensionSegmentCenterPt = (xyz + list3[0]) / 2.0;
						list2.Add(list3[0]);
					}
					else
					{
						num2 = xyz.DistanceTo(list3[1]);
						this.m_DimensionSegmentCenterPt = (xyz + list3[1]) / 2.0;
						list2.Add(list3[1]);
					}
					double num3 = Common.FeetToMM(num2) / (double)num;
					this.m_strDimensionSegmentTxt = string.Concat(new string[]
					{
						num3.ToString("f0"),
						"*",
						num.ToString(),
						"=",
						((int)num3 * num).ToString()
					});
				}
			}
			else
			{
				foreach (PlanarFace planarFace in this.m_lstPlanarFaceZ)
				{
					list.AddRange(GeometryHelper.GetAllEdgeList(planarFace));
				}
				list2 = GeometryHelper.LineWithLstCvIntersect(this.m_Centerline, list);
			}
			Grid grid = null;
			DbAxial dbAxial = null;
			if (base.GetDbAxialWithDir(this.m_LevelDir, out dbAxial))
			{
				double num4 = double.MaxValue;
				foreach (XYZ fixedXyz in list2)
				{
					double num5 = 0.0;
					Grid gridNearestXZY = dbAxial.GetGridNearestXZY(fixedXyz, ref num5);
					if (Geometry.LessThan(num5, num4))
					{
						num4 = num5;
						grid = gridNearestXZY;
					}
				}
				if (Geometry.IsEqual(num4, 0.0))
				{
					grid = null;
				}
			}
			AssistFunc.CompressArray(list2);
			foreach (XYZ startPoint in list2)
			{
				DetailCurve detailCurveWithPoint = CommonInterface.GetDetailCurveWithPoint(this.m_doc, startPoint, this.m_LevelDir);
				if (detailCurveWithPoint != null)
				{
					Reference reference = new Reference(detailCurveWithPoint);
					this.m_arRef.Append(reference);
				}
			}
			if (grid != null)
			{
				XYZ xyz2 = (grid.Curve as Line).Project(list2[0]).XYZPoint;
				xyz2 = new XYZ(xyz2.X, xyz2.Y, list2[0].Z);
				DetailCurve detailCurveWithPoint2 = CommonInterface.GetDetailCurveWithPoint(this.m_doc, xyz2, this.m_LevelDir);
				if (detailCurveWithPoint2 != null)
				{
					Reference reference2 = new Reference(detailCurveWithPoint2);
					this.m_arRef.Append(reference2);
				}
			}
		}

		private FamilyInstance m_FsStep;

		private List<PlanarFace> m_lstPlanarFaceZ = new List<PlanarFace>();

		private Line m_Centerline;

		private Line m_BottomAndBehindLine;

		private XYZ m_stepDir = XYZ.BasisY;

		private XYZ m_LevelDir = XYZ.BasisX;

		private ReferenceArray m_arRef = new ReferenceArray();

		private string m_strDimensionSegmentTxt = "";

		private XYZ m_DimensionSegmentCenterPt = XYZ.Zero;
	}
}
